package boardgamer.server;

import boardgamer.common.GameLog;
import boardgamer.common.GameState;
import boardgamer.common.GameStateChange;
import boardgamer.common.GameUpdate;
import boardgamer.common.SynchronizedObject;
import com.google.common.collect.ImmutableList;

import static com.google.common.base.Preconditions.checkNotNull;

public abstract class GameServer<GS extends GameState, C extends GameStateChange> {

  protected final SynchronizedObject<GS> syncState;
  private final GameLog<GS, C> log;

  public GameServer(GS initialGameState) {
    this.syncState = new SynchronizedObject<GS>(checkNotNull(initialGameState, "initialGameState"));
    this.log = new GameLog<GS, C>(initialGameState);
  }

  protected void onNewGameState(GS newGameState, C stateChange) {
    synchronized (syncState) {
      synchronized (log) {
        syncState.set(newGameState);
        log.add(new GameUpdate<GS, C>(stateChange, newGameState));
      }
    }
  }

  protected ImmutableList<GameUpdate<GS, C>> getUpdates(int firstTimestamp) {
    return log.getUpdates(firstTimestamp);
  }
  
  protected GameLog<GS, C> getGameLog() {
    return new GameLog<GS, C>(log);
  }
}
